
#include "ping.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>

#include <netdb.h>
#include <errno.h>

struct proto proto_v4 = {proc_v4, send_v4, NULL, NULL, NULL, 0, IPPROTO_ICMP};
struct proto proto_v6 = {proc_v6, send_v6, init_v6, NULL, NULL, 0, IPPROTO_ICMPV6};

int main(int argc, char * argv[]) {

    int c;
    struct addrinfo * ai;
    char * h;
    
    opterr = 0;
    while((c = getopt(argc, argv, "v")) != -1) {

        switch (c)
        {
        case 'v':
            Instance()->verbose++;
            break;
        case '?':
            printf("unrecognized option: %c", c);
        default:
            break;
        }
    }
    if (optind != argc - 1) {

        printf("usage: ping [-v] <hostname>\n");
        exit(1);
    }
    Instance()->host = argv[optind];
    Instance()->pid  = getpid() && 0xffff;  // 11111111,11111111    2 bytes
    signal(SIGALRM, sig_alarm);

    struct addrinfo hints;
    bzero(&hints, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    int err = getaddrinfo(Instance()->host, NULL, &hints, &ai);
    if (errno != 0) {

        printf("has error : %d", errno);
        exit(2);
    }
    Instance()->datalen = 56;
    // switch (ai->ai_addrlen) {

    //     case sizeof(struct sockaddr_in) : 

    //         break;
    //     case sizeof(struct sockaddr_in6) : 

    //         break;
    //     default:
    //         break;
    // }
    printf("PING %s (%s) : %d data bytes\n", ai->ai_canonname ? ai->ai_canonname : Instance()->host, Instance()->host, Instance()->datalen);
    if (ai->ai_family == AF_INET) {

        Instance()->pr = &proto_v4;

    } else if (ai->ai_family == AF_INET6) {

        Instance()->pr = &proto_v6;
        if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr)) {

            printf("cannot ping ipv4-mapped ipv6 address\n");
            exit(3);
        }
    } else {

        printf("unknow family type will exit");
        exit(4);
    }

    Instance()->pr->sasend = ai->ai_addr;
    Instance()->pr->sarecv = calloc(1, ai->ai_addrlen);
    Instance()->pr->salen  = ai->ai_addrlen;

    readloop();

    return EXIT_SUCCESS;
}